package utils

import (
	"bufio"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"path/filepath"
)

// CreateDir 创建目录
func CreateDir(dirPath string) (err error) {
	err = os.MkdirAll(dirPath, 0755)
	if err != nil {
		if !os.IsExist(err) {
			return nil
		}
	}
	return
}

// DirIsExist 判断目录是否存在
func DirIsExist(dirPath string) bool {
	s, err := os.Stat(dirPath)
	if err != nil {
		//log.Println(dirPath, err)
		return false
	}
	return s.IsDir()
}

// FileIsExist 判断文件是否存在  存在返回 true 不存在返回false
func FileIsExist(filePath string) bool {
	var exist = true
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		exist = false
	}
	return exist
}

// WriteFile 文件内容写入
func WriteFile(filePath, content string, append bool) bool {
	var (
		f    *os.File
		err  error
		flag int
	)
	dir, _ := path.Split(filepath.FromSlash(filePath))
	CreateDir(dir)
	if append {
		flag = os.O_CREATE | os.O_WRONLY | os.O_APPEND
	} else {
		flag = os.O_CREATE | os.O_WRONLY
	}
	f, err = os.OpenFile(filePath, flag, 0666) //打开文件
	if err != nil {
		log.Println(filePath, err)
		return false
	}
	_, err1 := io.WriteString(f, content+"\n") //写入文件(字符串)
	if err1 != nil {
		log.Println(filePath, err1)
		return false
	}
	return true
}

// ReadFile 普通小文件全量读取
func ReadFile(filePath string) (content []byte) {
	var err error
	if FileIsExist(filePath) {
		content, err = ioutil.ReadFile(filePath)
		if err != nil {
			log.Println(filePath, err)
		}
	}
	return
}

/**
* 一行一行的读文件
 */
//func ReadLine(filePth string, result func([]byte)) error {
func ReadLine(filePath string) (result []string) {
	if !FileIsExist(filePath) {
		return
	}
	f, err := os.Open(filePath)
	if err != nil {
		return
	}
	defer f.Close()
	bfRd := bufio.NewReader(f)
	for {
		line, _, err := bfRd.ReadLine()
		if err == io.EOF {
			break
		}
		result = append(result, string(line))
	}
	return result
}

// ReadBigFile 大文件读取
// 适合：常规带换行符，单行没有超过4069个字节的
func ReadBigFile(filePath string, handle func(string)) error {
	f, err := os.Open(filePath)
	defer func() { _ = f.Close() }()
	if err != nil {
		return err
	}
	buf := bufio.NewReader(f)
	for {
		// 读取文件 (行读取) ReadBytes('\n'),slice为[]byte
		slice, err2 := buf.ReadBytes('\n') // '\n'表示按行读取。 ','表示按英文逗号读取。
		if err2 == io.EOF {                // 如果读取到文件末尾
			break
		}
		// 处理函数slice为[]byte,转字符再处理
		handle(string(slice))
	}
	return nil
}

// ReadBinaryFile 大文件读取
// 适合：读取二进制文件，如音频视频流
func ReadBinaryFile(filePath string, handle func(string)) error {
	//start1 := time.Now()
	f, err := os.Open(filePath)
	if err != nil {
		return err
	}
	defer func() { _ = f.Close() }()
	// 设置每次读取字节数
	buffer := make([]byte, 1024)
	for {
		n, err2 := f.Read(buffer)
		// 控制条件,根据实际调整
		if err2 != nil && err2 != io.EOF {
			log.Println(err2)
		}
		if n == 0 || err2 == io.EOF {
			break
		}
		// 如下代码打印出每次读取的文件块(字节数)
		handle(string(buffer[:n]))
	}
	return nil
	//fmt.Println("spend time: ", time.Now().Sub(start1))
}
